package cn.remex.db;

import cn.remex.core.reflect.ReflectUtil;
import cn.remex.core.util.Param;
import cn.remex.db.lambdaapi.ColumnPredicate;
import cn.remex.db.rsql.RsqlConstants;
import cn.remex.db.rsql.RsqlUtils;
import cn.remex.db.rsql.model.Modelable;

import java.util.List;

/**
 * 名称：
 * 缩写：
 * 用途：
 * Created by yangy on 2016/8/5 0005.
 */
public class Query<T extends Modelable, ParentType extends Modelable> {
	private Container container;
	private DbCvo<T, ParentType> dbCvo;

	Query(Container container, DbCvo<T, ParentType> dbCvo) {
		this.container = container;
		this.dbCvo = dbCvo;
	}


	public DbRvo<T> executeQuery() {
		return container.executeQuery(dbCvo);
	}

	public T queryBeanById(String examTaskId) {
		this.dbCvo.filterById(examTaskId);
		return queryBean();
	}

	public DbRvo<T> update() {
		return container.update(dbCvo);
	}
	public DbRvo<T> delete() {
		return container.delete(dbCvo);
	}
	public DbRvo<T> query() {
		return container.query(dbCvo);
	}
	public DbRvo<T> store(final T obj) {
		dbCvo.setOper(RsqlConstants.SqlOper.store);
		// dbCvo.setDataType((DT_base + DT_object).equals(dbCvo.getDataType()) ? DT_whole : dbCvo.getDataType());
		return container.store(obj, dbCvo);//如果修改了默认值，则使用当前的
	}
	//---lambda控制方式的简化方法---------------------//
	public T queryBean() {
		List<T> beans = container.query(dbCvo).obtainBeans();
		return beans.size() > 0 ? beans.get(0) : null;
	}
	public List<T> queryBeans() {
		return container.query(dbCvo).obtainBeans();
	}
	public<ST extends Modelable> DbRvo<ST> queryCollectionField(ColumnPredicate<T> cp, Object foreignKey) {
		Param<String> fieldNameParam = new Param<>(null);
		ReflectUtil.eachFieldWhenGet(dbCvo.getBeanClass(), bean -> cp.init((T) bean), fieldName -> fieldNameParam.param = fieldName);
		return RsqlUtils.doListColumn_select(this.container.getSpaceName(), dbCvo.getBeanClass(), fieldNameParam.param, foreignKey);
	}

	public void update(T model, ColumnPredicate<T> cp) {
		this.dbCvo.filterById(model.getId());
		ReflectUtil.eachFieldWhenGet(model, c -> cp.init((T) c), f-> this.dbCvo.assignColumn(cp, ReflectUtil.invokeGetter(f, model)));
		update();
	}
}
